// project.c ... project scan functions
// part of Multi-attribute Linear-hashed Files
// Manage creating and using Projection objects
// Last modified by Xiangjun Zai, Mar 2025

#include <stdbool.h>
#include "defs.h"
#include "project.h"
#include "reln.h"
#include "tuple.h"
#include "util.h"



// A suggestion ... you can change however you like

struct ProjectionRep {
    Reln    rel;       // need to remember Relation info
    int    *attrIndexes; // 存储投影所需的属性索引
    Count   numAttrs;   // 投影属性的数量
};

// take a string of 1-based attribute indexes (e.g. "1,3,4")
// set up a ProjectionRep object for the Projection
Projection startProjection(Reln r, char *attrstr)
{
    Projection new = malloc(sizeof(struct ProjectionRep));
    assert(new != NULL);
    
    // 分配内存存储属性索引
    new->attrIndexes = malloc(nattrs(r) * sizeof(int));
    assert(new->attrIndexes != NULL);
    new->numAttrs = 0;
    // 检查是否是 * 通配符
    if (strcmp(attrstr, "*") == 0) {
        // 如果是 *，则投影所有属性
        for (Count i = 0; i < nattrs(r); i++) {
            new->attrIndexes[new->numAttrs++] = i;
        }
    }else{

        // 解析属性索引字符串
        
        char *token = strtok(attrstr, ",");
        while (token != NULL) {
            int index = atoi(token) - 1; // 将1-based索引转换为0-based索引
            if (index < 0 || index >= nattrs(r)) {
                free(new->attrIndexes);
                free(new);
                return NULL; // 无效的属性索引
            }
            new->attrIndexes[new->numAttrs++] = index;
            token = strtok(NULL, ",");
        }
    
    }
    new->rel = r;
    return new;
}

void projectTuple(Projection p, Tuple t, char *buf)
{
    // TODO: Implement projection of tuple 't' according to 'p' and store result in 'buf'
    // 分配内存用于存储提取的属性值
    char **vals = malloc(nattrs(p->rel) * sizeof(char *));
    assert(vals != NULL);
    tupleVals(t,vals); // 获取元组的属性值数组
    char *result = buf;
    for (Count i = 0; i < p->numAttrs; i++) {
        int index = p->attrIndexes[i];
        strcpy(result, vals[index]); // 复制属性值到结果缓冲区
        result += strlen(vals[index]) ; // 更新结果缓冲区的指针
        if (i < p->numAttrs - 1) {
            *result++ = ','; // 添加逗号分隔符
        }
        //printf("attr%d %s\n",i,vals[index]);
    }
    *result = '\0'; // 添加字符串结束符

    freeVals(vals, nattrs(p->rel)); // 释放属性值数组
}

void closeProjection(Projection p)
{
    // TODO
}
